﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Linq;
using System.Configuration;
using System.Windows.Forms;
using System.Reflection;
using System.Data.SqlClient;

namespace Test2.Model
{
    class DatabaseLinqRepository : iDatabaseRepository
    {
        public DataTable getKlanten()
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            return this.LINQToDataTable<Klanten>(facdc.Klantens);
        }

        /// <summary>
        /// Geeft de Klant terug met de gevraagde klantID
        /// </summary>
        /// <param name="klantID">Integer met de klantID</param>
        /// <returns>DataTable</returns>
        public DataTable getKlantByID(int klantID)
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            var klant = from k in facdc.Klantens
                        where k.klantID == klantID
                        select k;
            return this.LINQToDataTable<Klanten>(klant);
        }

        public DataTable getKlantenVoornaamNaam()
        {
            //how to in LINQ? voor enkel voor en achternaam
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            /*var klanten = from k in facdc.Klantens
                          select new {
                            Voornaam = k.voornaam,
                            Naam = k.naam
                          };*/
            return this.LINQToDataTable<Klanten>(facdc.Klantens);
        }

        public DataTable getKlantenVoornaamNaamFilter(string input)
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            var filtered = from k in facdc.Klantens
                           where k.naam.StartsWith(input) || k.voornaam.StartsWith(input)
                           select k;
            return LINQToDataTable<Klanten>(filtered);
        }

        public DataTable getFacturen()
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            return this.LINQToDataTable<Facturen>(facdc.Facturens);
        }

        public DataTable getFacturenByKlantID(int klantID)
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            var factuurtjes = from fac in facdc.Facturens
                              where fac.klantID == klantID
                              select fac;
            return this.LINQToDataTable<Facturen>(factuurtjes);
        }

        public DataTable getFactuurDetails()
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            return this.LINQToDataTable<FactuurDetail>(facdc.FactuurDetails);
        }

        public DataTable getFactuurDetailsByFactuurID(int factuurID)
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            var facdetails = from fd in facdc.FactuurDetails
                              where fd.factuurID == factuurID
                              select fd;
            return this.LINQToDataTable<FactuurDetail>(facdetails);
        }

        public string getLaatsteFactuurnummer()
        {
            string maxnr = "";
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            var factuurnummers = from f in facdc.Facturens orderby f.factuurID descending select (f.factuurnummer);
            if (factuurnummers.Count() > 0) maxnr = factuurnummers.First();
            return maxnr;
        }

        public void insertKlant(string voornaam, string naam, string adres, string plaats, short postcode, string telefoon, string email)
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            Table<Klanten> tblKlanten = facdc.Klantens;
            Klanten k=new Klanten();
            k.voornaam=voornaam;
            k.naam=naam;
            k.adres=adres;
            k.plaats=plaats;
            k.postcode=postcode;
            k.telefoon=telefoon;
            k.email=email;
            tblKlanten.InsertOnSubmit(k);
            tblKlanten.Context.SubmitChanges();
        }
        
        public void insertFactuur(int klantID, string factuurnummer, DateTime datum, string opmerkingen, List<FactuurDetail> fds)
        {
            LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
            Table<Facturen> tblFacturen = facdc.Facturens;
            Table<FactuurDetail> tblFactuurDetail = facdc.FactuurDetails;
            Facturen fac = new Facturen();
            fac.klantID = klantID;
            fac.factuurnummer = factuurnummer;
            fac.datum = datum;
            fac.opmerkingen = opmerkingen;
            foreach (FactuurDetail fd in fds)
            {
                fd.Facturen = fac;
                tblFactuurDetail.InsertOnSubmit(fd);
            }
            try
            {
                tblFacturen.InsertOnSubmit(fac);
                tblFacturen.Context.SubmitChanges();
            }
            catch (SqlException)
            {
                fac.factuurnummer = int.Parse(factuurnummer) + 1 + "";
                tblFacturen.Context.SubmitChanges();
            }
        }

        public bool updateKlant(int klantID, string voornaam, string naam, string adres, string plaats, short postcode, string telefoon, string email, byte[] modify_date)
        {
            try
            {
                LINQfacturatiesDataContext facdc = new LINQfacturatiesDataContext();
                Table<Klanten> tblKlanten = facdc.Klantens;
                Klanten klant = (from k in facdc.Klantens
                                 where k.klantID == klantID
                                 select k).SingleOrDefault();
                klant.voornaam = voornaam;
                klant.naam = naam;
                klant.adres = adres;
                klant.plaats = plaats;
                klant.postcode = postcode;
                klant.telefoon = telefoon;
                klant.email = email;
                tblKlanten.Context.SubmitChanges(ConflictMode.FailOnFirstConflict);
                return true;
            }
            catch (ChangeConflictException)
            {
                //Mogelijk om conflicten automatisch te laten resolven met facdc.ChangeConflicts
                //Hier laten we de user beslissen
                return false;
            }
        }

        /// <summary>
        /// Lijst die de datatable genereert.
        /// </summary>
        /// <typeparam name="T">Type van de tabel</typeparam>
        /// <param name="varlist">De te converteren lijst</param>
        /// <returns>DataTable met de gegevens</returns>
        public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
        {
            DataTable dtReturn = new DataTable();

            // column names 
            PropertyInfo[] oProps = null;

            if (varlist == null) return dtReturn;

             foreach (T rec in varlist)
                {
                // Use reflection to get property names, to create table, Only first time, others 
                if (oProps == null)
                {
                    oProps = ((Type)rec.GetType()).GetProperties();
                    foreach (PropertyInfo pi in oProps)
                    {
                         Type colType = pi.PropertyType;

                     if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()==typeof(Nullable<>)))
                     {
                             colType = colType.GetGenericArguments()[0];
                     }

                    dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
                   }
              }
              DataRow dr = dtReturn.NewRow();
          foreach (PropertyInfo pi in oProps)
          {
               dr[pi.Name] = pi.GetValue(rec, null) == null ?DBNull.Value :pi.GetValue
               (rec,null);
          }

          dtReturn.Rows.Add(dr);
         }
         return dtReturn;
        }
    }
}
